
package highgui

// #include <opencv/cv.h>
// #include <opencv/highgui.h>
import "C"

import (
	"ry/mat"
	"unsafe"
)

type Window struct {
	image *C.IplImage
	name string
	open bool
	rows,cols int
	scale int
}

func (win *Window) destroy () {
	win.Hide ()
}

func NewWindow (name string, scale int) *Window {

	win := new (Window) 
	win.name = name
	win.open = false
	win.scale = scale

	return win
}

func (win *Window) Hide () {

	if win.open {
		C.cvDestroyWindow (C.CString (win.name))
	}

	if win.image != nil {
	
		C.cvReleaseImage (&win.image)
	}

	win.open = false
}

func (win *Window) Show (m mat.Interface, scale float64) {

	if !win.open {
		C.cvNamedWindow (C.CString (win.name), 1)
		win.open = true
	}

	if m != nil {
	
	rows, cols := m.Dims ()
	
		if win.image == nil || win.rows != rows || win.cols != cols {
			if win.image != nil {
				C.cvReleaseImage (&win.image)
			}
			win.image = C.cvCreateImage (C.cvSize (C.int (cols*win.scale), C.int (rows*win.scale)), C.int (8), 3)
			win.rows = rows
			win.cols = cols
		}

		for i := 0; i < rows; i++ {
			for j := 0; j < cols; j++ {
				r,g,b := m.ColorAt (i,j)
				cr := C.double (scale * r)
				cg := C.double (scale * g)
				cb := C.double (scale * b)
				for ki := 0; ki < win.scale; ki++ {
					for kj := 0; kj < win.scale; kj++ {
						C.cvSet2D (unsafe.Pointer (win.image), C.int (i*win.scale+ki),C.int (j*win.scale+kj), 
							C.cvScalar (cb,cg,cr, 1.0))
					}
				}
			}
		}

		C.cvShowImage (C.CString (win.name), unsafe.Pointer (win.image))
	}
}

func Save (m mat.Interface, scale float64, file string) {

	rows, cols := m.Dims ()

	image := C.cvCreateImage (C.cvSize (C.int (cols), C.int (rows)), C.int (8), 3)
	
	for i := 0; i < rows; i++ {
		for j := 0; j < cols; j++ {
			v := C.double (scale * m.FloatAt (i,j))
			C.cvSet2D (unsafe.Pointer (image), C.int (i),C.int (j), 
				C.cvScalar (v,v,v, 0.0))
		}
	}
	
	C.cvSaveImage (C.CString (file), unsafe.Pointer (image))
	
	C.cvReleaseImage (&image)
}

func WaitKey (delay int) int {

	return int (C.cvWaitKey (C.int (delay)))
}
